import { Injectable, ErrorHandler, Injector } from '@angular/core';
import { Http, Response, RequestOptionsArgs, Headers } from '@angular/http';
import { Buffer } from 'buffer';
import { config } from './config';
import { Router } from '@angular/router';
// tslint:disable-next-line:import-blacklist
import { Observable } from 'rxjs';
import { NzModalService } from 'ng-zorro-antd';
import { Md5 } from 'ts-md5';

/** 判断是否存在当前用户当前角色 */
export class RoleRight {
    static getisRole(user: any, role: any) {
        let isexists = false;
        const storage = JSON.parse(window.localStorage.getItem('scyysoft'));
        if (user && storage.name) {
            isexists = (storage.name as string).indexOf(user) > -1;
        }
        if (role && storage.roleName && storage.roleName.length > 0) {
            isexists = (storage.roleName as Array<any>).findIndex((r) => { return r === role }) > -1;
        }
        return isexists;
    }
    static getStorage() {
        return JSON.parse(window.localStorage.getItem('scyysoft'));
    }
}

namespace kalend.common {
    export module win {
        // tslint:disable-next-line:class-name
        class jq {
            constructor(str: any) { }
            // tslint:disable-next-line:member-ordering
            kalends: {
                confirm: (msg: String, funConfirm: any) => {},
                textarea: (options: any) => {},
                loader: (msg: String) => {}
            };
        };
        // tslint:disable-next-line:no-shadowed-variable
        export const $: jq = window['jQuery'];
    };
};

namespace kalend.core {
    @Injectable()
    // tslint:disable-next-line:no-shadowed-variable
    export class CustomErrorHandler extends ErrorHandler {
        constructor(private injector: Injector, private modalService: NzModalService) {
            super();
        }

        warning(msg): void {
            // if (this.modalService.warning) {
            //     this.modalService.warning({
            //         nzTitle: '提示信息',
            //         nzContent: `${msg}`
            //     });
            // } else {
                alert(msg);
            //}
        }
        handleError(error: any) {
            console.log('handler:' + error);
            const err_rejec = error.rejection;
            if (err_rejec) {
                let msg;
                if (err_rejec instanceof Response) {
                    switch (err_rejec.status) {
                        case 0:
                            msg = '网络异常或服务停止';
                            break;
                        case 404:
                            msg = `请求接口错误，接口地址：${err_rejec.url}`;
                            break;
                        default:
                            msg = err_rejec.statusText;
                            break;
                    }
                } else if (err_rejec.message) {
                    msg = err_rejec.message;
                    if (err_rejec.errcode) {
                        switch (+err_rejec.errcode) {
                            case 20000: // 需要重新登录
                                if (this.injector) {
                                    const router = this.injector.get(Router);
                                    router.navigate([`/login`]);
                                } else {
                                    msg = '登录超期，请退出重新登录';
                                }
                                break;
                            default:
                                console.error(err_rejec.errcode);
                                break;
                        }
                    }
                } else {
                    msg = '未知错误';
                    console.error(error);
                }
                this.warning(msg);
            }
            super.handleError(error);
        }
    }
}
namespace kalend.service {
    class MaskLayer {
        private curReqCnt = 0;
        private handle: any;
        private ms = 500;
        private loader: (msg: String) => {} = common.win.$.kalends.loader;
        /**
         *
         */
        constructor() {
        }
        private show() {
            if (this.handle) {

            } else {
                // console.log('加载遮罩层');
                //this.loader('show');
                this.handle = setInterval(() => {
                    if (this.curReqCnt === 0) {
                        this.hide();
                    } else {
                        console.log('setInterval', this.curReqCnt);
                    }
                }, this.ms);
            }
        };
        private hide() {
            clearInterval(this.handle);
            this.handle = undefined;
            //this.loader('hide');
            // console.log('去除遮罩层');
        }
        add = () => {
            if (this.curReqCnt === 0) {
                this.show();
            }
            this.curReqCnt++;
        }
        remove() {
            this.curReqCnt--;
        }
    }
    const maskLayer: MaskLayer = new MaskLayer();
    const key = 'scyysoft';

    export class ServiceBasics {
        get apiServiceURL(): String {
            return config.apiprefix;
        }
        constructor(private urlPrefix: String, private http: Http) {
        }
        private urlBuilder(url: string): string {
            let _url = url;
            if (_url.indexOf('?') >= 0) {
                _url += '&&';
            } else {
                _url += '?';
            }
            const a = Math.floor(Date.now() / 1000);
            _url += `timestamp=${a}`;
            return encodeURI(_url);
        };
        // private urlBuilder(url: String): string {
        //     const _url = `${this.apiServiceURL}${this.urlPrefix}${url}`+;
        //     return _url;
        // }

        private requestOptionsArgsFac(url: any, args?: RequestOptionsArgs) {
            args = args || {};
            console.log(args)
            if (args.headers) {
            } else {
                args.headers = new Headers({ credentials: true });
            }
            if (typeof args.withCredentials as string === 'boolean') {
            } else {
                // args.withCredentials = true;
                args.headers.set('Access-Control-Allow-Credentials', 'true');
            };
            console.log(url);
            args.headers.set('tokensoft', this.sign(url + key));
            const stru = window.location.hash.substring(1);
            if (stru !== '/login') {
                args.headers.set('route', window.location.hash.substring(1));
            }
            if (RoleRight.getStorage()) {
                args.headers.set('epid', RoleRight.getStorage()._id);
            }

            return args;
        }
        private maskLayer(main: Observable<Response>, hide?: any) {
            if (hide) {
                return main.toPromise()
                    .then((res: Response) => {
                        return res;
                    })
                    .catch((err) => {
                        return Promise.reject(err);
                    });
            } else {

                maskLayer.add();
                return main.toPromise()
                    .then((res: Response) => {
                        maskLayer.remove();
                        return res;
                    })
                    .catch((err) => {
                        maskLayer.remove();
                        return Promise.reject(err);
                    });
            }
        }


        private downloadFile(fileName: string, data: Blob) {
            const url = URL.createObjectURL(data);
            const a = document.createElement('a');
            document.body.appendChild(a);
            a.href = url;
            a.download = fileName;
            a.click();
            a.remove(); // 将a标签移除
        }
        private responsed(res: Response) {
            if (res.headers.has('tokensoft')) {
                config.safetyInfo.setToken(res.headers.get('tokensoft'));
            }
            // if (res.headers.has('content-disposition')) {
            //     const disstr = res.headers.get('content-disposition');
            //     let fileName;
            //     if (disstr) {
            //         const val = parse(disstr).parameters;
            //         fileName = decodeURI(val.filename);
            //     }
            //     const buf = new Buffer(res.json().data);
            //     this.downloadFile(fileName, new Blob([buf.buffer]));
            //     return;
            // }
            if (res.headers.has('content-disposition')) {
                const disstr = res.headers.get('content-disposition');
                let fileName;
                if (disstr) {
                    fileName = disstr.split(';')[1].split('filename=')[1];
                    const fileNameUnicode = disstr.split('filename*=')[1];
                    if (fileNameUnicode) {// 当存在 filename* 时，取filename* 并进行解码（为了解决中文乱码问题）
                        fileName = decodeURI(fileNameUnicode.split("''")[1]);
                    } else {
                        fileName = fileName.replace('"', '').replace('"', '');
                    }
                }
                const buf: any = new Buffer(res.json().data);
                this.downloadFile(fileName, new Blob([buf.buffer]));
                return;
            } else {
                const value = res.json();
                if (value.code === 1) {
                    return Promise.resolve(value.data);
                } else {
                    return Promise.reject(value.data || value || {});
                }
            }
        }
        protected async httpget(url: String, options?: any): Promise<any> {
            // options = options || {};
            url = this.urlBuilder(`${this.urlPrefix}${url}`);
            const req = this.http.get(`${this.apiServiceURL}${url}`, this.requestOptionsArgsFac(url));
            // let res: Response;
            // if (options && options.noMask) {
            //     res = await req.toPromise();
            // } else {
            //     res = await this.maskLayer(req, hide);
            // }
            // return this.responsed(res);
            // const req = this.http.get(this.urlBuilder(url), this.requestOptionsArgsFac(url));
            const res = await this.maskLayer(req);
            return this.responsed(res);
        }
        protected async httppost(url: String, body?: any, options?: any) {
            url = this.urlBuilder(`${this.urlPrefix}${url}`);
            const req = this.http.post(`${this.apiServiceURL}${url}`, body || {}, this.requestOptionsArgsFac(url));
            // const req = this.http.post(this.urlBuilder(url), body || {}, this.requestOptionsArgsFac(url));
            const res = await this.maskLayer(req);
            return this.responsed(res);
        }
        sign(endpoint: string) {
            return Md5.hashStr(endpoint.substring(1)).toString();
        }
    }
}
namespace kalend.web {
    let __current: LoginUser;
    export class LoginUsers {
        id: String;
        name: String;
        features: Array<any>;
        menus: Array<any>;
        /** TODO */
        area: any;

        static get key() {
            return 'scyysoft';
        }

        static get current(): LoginUser {
            let user: LoginUser = null;
            if (__current) {
                user = __current;
            } else {
                const userStr = window.localStorage.getItem(this.key);
                if (userStr) {
                    try {
                        user = JSON.parse(userStr);
                        __current = user;
                    } catch (err) {
                        // TODO跳转到错误页
                        console.log('存储的用户信息不正确', err);
                    }
                }
            }
            return user;
        }

        static login(userInfo): void {
            window.localStorage.setItem(this.key, JSON.stringify(userInfo));
        }
        static loginout(): void {
            __current = undefined;
            window.localStorage.removeItem(this.key);
        }
        static get isLogin(): Boolean {
            return !!this.current;
        }
        static getFeatures(key: String): Array<any> {
            return [];
        }
    }
}

export const $ = kalend.common.win.$ as any;
export const confirm = kalend.common.win.$.kalends.confirm;
export const textarea = kalend.common.win.$.kalends.textarea;
export class CustomErrorHandler extends kalend.core.CustomErrorHandler { }
export class ServiceBasic extends kalend.service.ServiceBasics { }

// tslint:disable-next-line:eofline
export class LoginUser extends kalend.web.LoginUsers { }